package org.eredlab.g4.rif.util;

import java.util.Hashtable;
import java.util.Iterator;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eredlab.g4.arm.service.MonitorService;
import org.eredlab.g4.arm.vo.UserInfoVo;
import org.eredlab.g4.bmf.base.IReader;
import org.eredlab.g4.bmf.util.SpringBeanLoader;
import org.eredlab.g4.ccl.datastructure.Dto;
import org.eredlab.g4.ccl.datastructure.impl.BaseDto;
import org.eredlab.g4.ccl.util.G4Utils;

/**
 * Session监听器 完成对Seesion会话资源的实时监控
 * 
 * @author 熊春
 * @since 2010-09-03
 * @see HttpSessionBindingListener
 */
public class SessionListener implements HttpSessionListener {
	
	private static Log log = LogFactory.getLog(SessionListener.class);
	
	// 集合对象，保存session对象的引用
	static Hashtable ht = new Hashtable();

	/**
	 * 实现HttpSessionListener接口，完成session创建事件控制
	 * 说明：此时的Session状态为无效会话，只有用户成功登录系统后才将此Session写入EAHTTPSESSION表作为有效SESSION来管理
	 */
	public void sessionCreated(HttpSessionEvent event) {
		//HttpSession session = arg0.getSession();
		//ht.put(session.getId(), session);
		//log.info("创建了一个Session连接:" + session.getId() + " " + Util.getCurrentTime());
	}

	/**
	 * 实现HttpSessionListener接口，完成session销毁事件控制
	 */
	//对于会话信息的操作都是基于会话的id来做的！能够进入到会话信息表中的记录都是能够合格登录的用户，否则不会有记录！
	public void sessionDestroyed(HttpSessionEvent event) 
	{
		System.out.println("提示：当前会话已经失效，正在保存事件。。。。。。。。");
		HttpSession session = event.getSession();
		//这个返回的sessionContainer对象无需判断是否会为空，无论用户是否登录总会返回一个不为null的对象，只不过里面客户实体对象是否为null就不一定了！
		SessionContainer sessionContainer =  (SessionContainer)session.getAttribute("SessionContainer");
		//将当前同会话关联的用户实体释放！
		sessionContainer.setUserInfo(null); //配合RequestFilter进行拦截
		sessionContainer.cleanUp();
		MonitorService monitorService = (MonitorService)SpringBeanLoader.getSpringBean("monitorService");
		//无论是请求退出，还是会话时间到了退出，都会通过当前的会话的id来将会话信息删除！
		Dto dto = new BaseDto();
		dto.put("sessionid", session.getId());
		//从会话信息记录表中删除当前会话信息，删除的方式是通过会话id来实现的！如果不删除将导致单用户登录模式无法登录，直到记录被删除！
		monitorService.deleteHttpSession(dto);
		//并将当前会话信息移除！删除会话后别忘啦移除！如果不移除对于那种只能登陆一个账户的登录模式会导致无法登录，直到会话自己销毁！
		ht.remove(session.getId());
		log.info("销毁了一个Session连接:" + session.getId() + " " + G4Utils.getCurrentTime());
	}
	
	/**
	 * 增加一个有效Session
	 * @param session
	 */
	//这里的增加并不是总是增加一个会话记录，而是只有在当前的会话id值没有在会话信息表中存在时才会添加，否则不做任何操作！因此会话信息表中的记录不会存在会话id相同的记录！
	static public void addSession(HttpSession session, UserInfoVo userInfo) 
	{
		ht.put(session.getId(), session);
		IReader g4Reader = (IReader)SpringBeanLoader.getSpringBean("g4Reader");
		MonitorService monitorService = (MonitorService)SpringBeanLoader.getSpringBean("monitorService");
		//通过会话的id来查询是否有记录，如果有记录就代表已经登陆过了，否则没有登录或者退出了系统！
		UserInfoVo usInfo = (UserInfoVo)g4Reader.queryForObject("Monitor.queryHttpSessionsByID", session.getId());
		if(G4Utils.isEmpty(usInfo))
		{
			//如果没有指定id的会话，就添加一个有效的会话记录！否则不会去添加！
			monitorService.saveHttpSession(userInfo);
		}
	}

	/**
	 * 返回全部session对象集合
	 * @return
	 */
	static public Iterator getSessions() 
	{
		return ht.values().iterator();
	}

	/**
	 * 依据session id返回指定的session对象
	 * @param sessionId
	 * @return
	 */
	static public HttpSession getSessionByID(String sessionId)
	{
		//通过会话的id来得到装载在集合中的会话对象！
		return (HttpSession) ht.get(sessionId);
	}
}
